home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / lalr.lha / lalr / src / Debug.mi < prev    next >
Text File  |  1992-08-18  |  25KB  |  1,088 lines

  1. (* compute debugging information *)
  2.  
  3. (* $Id: Debug.mi,v 1.5 1992/08/07 15:22:49 grosch rel $ *)
  4.  
  5. (* $Log: Debug.mi,v $
  6.  * Revision 1.5  1992/08/07  15:22:49  grosch
  7.  * allow several scanner and parsers; extend module Errors
  8.  *
  9.  * Revision 1.4  1991/11/21  14:53:14  grosch
  10.  * new version of RCS on SPARC
  11.  *
  12.  * Revision 1.3  90/06/12  16:53:54  grosch
  13.  * renamed main program to lalr, added { } for actions, layout improvements
  14.  * 
  15.  * Revision 1.2     89/05/02  14:35:37  vielsack
  16.  * new option: -v (verbose)
  17.  * NoTrace is used instead of NoDebug
  18.  * 
  19.  * Revision 1.1     89/01/12  18:11:43  vielsack
  20.  * to supress the trace of a read reduce conflict
  21.  * the left hand side must be the same too
  22.  * 
  23.  * Revision 1.0     88/10/04  14:36:05  vielsack
  24.  * Initial revision
  25.  * 
  26.  *)
  27.  
  28. IMPLEMENTATION MODULE Debug;
  29.  
  30. FROM Automaton    IMPORT tAss, tRep, tItem, tState, tIndex, tProduction, Infinite,
  31.                 StartSymbol, ProdList, StateArrayPtr, tStateIndex,
  32.                 ItemArrayPtr, tItemIndex, ItemIndex, ProdArrayPtr, tProdIndex;
  33. FROM Continue    IMPORT Value;
  34. FROM DynArray    IMPORT ExtendArray, MakeArray, ReleaseArray;
  35. FROM IO        IMPORT tFile, WriteC, WriteS, WriteI, WriteNl;
  36. FROM Sets    IMPORT tSet, Extract, Include, Exclude, MakeSet, ReleaseSet,
  37.             Assign, Intersection, IsElement, IsEmpty;
  38. FROM Strings    IMPORT Length, Char, tString;
  39. FROM Idents    IMPORT tIdent, GetString;
  40. FROM SYSTEM    IMPORT ADR, TSIZE;
  41. FROM TokenTab    IMPORT MINTerm, MAXTerm, MINNonTerm, MAXNonTerm, Terminal,
  42.             NonTerminal, Vocabulary, TokenError, TokenToSymbol;
  43.   
  44.   CONST
  45.     InitTab = 0;
  46.     MaxTabA = 40;
  47.     MaxTabB = 30;
  48.     MaxTabC = 50;
  49.     MaxTabD = 40;
  50.     InitChainLength = 50;
  51.  
  52.   TYPE
  53.     tItemPath = RECORD
  54.     count  : SHORTCARD;
  55.     max    : LONGINT;
  56.     path   : POINTER TO ARRAY [1..Infinite] OF tItemIndex;
  57.       END;
  58.     
  59.     tProdPathElmt = RECORD
  60.     Prod : tProdIndex;
  61.     Pos  : tIndex;
  62.       END;
  63.  
  64.     tProdPath = RECORD
  65.     count : SHORTCARD;
  66.     max   : LONGINT;
  67.     path  : POINTER TO ARRAY [1..Infinite] OF tProdPathElmt;
  68.       END;
  69.  
  70.     tItemChainElmt = RECORD
  71.     Item : tItemIndex;
  72.     Last : tIndex;
  73.       END;
  74.     
  75.     tItemChain = RECORD
  76.     reached : tSet;
  77.     level    : LONGINT;
  78.     count    : LONGINT;
  79.     max    : LONGINT;
  80.     chain    : POINTER TO ARRAY [1..Infinite] OF tItemChainElmt;
  81.       END;
  82.  
  83.   VAR
  84.     PathA : tProdPath;
  85.     PathC : tItemPath;
  86.     PathB : tItemPath;
  87.     ChainD: tItemChain;
  88.     PathD : tProdPath;
  89.  
  90. PROCEDURE InformIgnored (Item: tItemIndex; t: Terminal);
  91.     BEGIN
  92.       WriteS (dFile,'ignored                 ');
  93.       WriteItem (Item,t);
  94.     END InformIgnored;
  95.  
  96. PROCEDURE InformLowPri (Item: tItemIndex; t: Terminal);
  97.     BEGIN
  98.       WriteS (dFile,'ignored (precedence)    ');
  99.       WriteItem (Item,t);
  100.     END InformLowPri;
  101.  
  102. PROCEDURE InformRightAss (Item: tItemIndex; t: Terminal);
  103.     BEGIN
  104.       WriteS (dFile,'ignored (associativity) ');
  105.       WriteItem (Item,t);
  106.     END InformRightAss;
  107.  
  108. PROCEDURE InformLeftAss (Item: tItemIndex; t: Terminal);
  109.     BEGIN
  110.       WriteS (dFile,'ignored (associativity) ');
  111.       WriteItem (Item,t);
  112.     END InformLeftAss;
  113.  
  114. PROCEDURE InformKept (Item: tItemIndex; t: Terminal);
  115.     BEGIN
  116.       WriteS (dFile,'retained                ');
  117.       WriteItem (Item,t);
  118.     END InformKept;
  119.  
  120. PROCEDURE InformConflict (kind: tConflict);
  121.     BEGIN
  122.       CASE kind OF
  123.     ShRed     : WriteS (dFile, 'there is a read reduce conflict');
  124.       | RedRed     : WriteS (dFile, 'there is a reduce reduce conflict');
  125.       | ShRedRed : WriteS (dFile, 'there is a read-reduce-reduce conflict');
  126.       ELSE;
  127.       END;
  128.       WriteNl (dFile);
  129.     END InformConflict;
  130.  
  131. PROCEDURE NewLine;
  132.     BEGIN
  133.       WriteNl (dFile);
  134.     END NewLine;
  135.     
  136. PROCEDURE WriteItem (Item: tItemIndex; t: Terminal);
  137.     VAR
  138.       length : CARDINAL;
  139.       i : tIndex;
  140.       p : tProduction;
  141.     BEGIN
  142.       WITH ItemArrayPtr^[Item] DO
  143.     p := ADR (ProdArrayPtr^[Prod]);
  144.     WriteVoc (p^.Left,length);
  145.     WriteS (dFile,' -> ');
  146.     length := 0;
  147.     WITH p^ DO
  148.       IF Len = 0 THEN
  149.         WriteS (dFile,'-Epsilon-.');
  150.       ELSE
  151.         IF Pos = 0 THEN
  152.           WriteS (dFile,'.');
  153.         END;
  154.         FOR i:=1 TO Len DO
  155.           WriteVoc (Right[i],length);
  156.           IF Pos = i THEN
  157.         WriteS (dFile,'.');
  158.           ELSE
  159.         WriteS (dFile,' ');
  160.           END;
  161.         END;
  162.       END;
  163.     END;
  164.     IF Pos = p^.Len THEN
  165.       WriteS (dFile,' {');
  166.       WriteVoc (t,length);
  167.       WriteS (dFile,'}');
  168.     END;
  169.  
  170.     WriteNl (dFile);
  171.       END;
  172.     END WriteItem;
  173.  
  174. PROCEDURE DebugHead (State: tStateIndex);
  175.     BEGIN
  176.       IF NoTrace THEN RETURN END;
  177.       WriteS (dFile,'State ');
  178.       WriteI (dFile,State,1);
  179.       WriteNl (dFile);
  180.       WriteNl (dFile);
  181.     END DebugHead;
  182.   
  183. PROCEDURE DebugEnd;
  184.     BEGIN
  185.       IF NoTrace THEN RETURN END;
  186.       WriteNl (dFile);
  187.     END DebugEnd;
  188.  
  189.   PROCEDURE DebugState
  190.     (      State : tStateIndex;           (* inconsitent State *)
  191.       VAR CS    : tSet);           (* Conflict Set *)
  192.  
  193.   (* Erzeuge Zusatzinformation zum Zustand 'State' mit Konfliktmenge 'Set' *)
  194.   (* wird fuer jeden inkonsitenten Zustand ausgefuehrt *)
  195.  
  196.     VAR
  197.       Item : tItemIndex;
  198.       s : tSet;
  199.       EI: tSet;         (* Explained Items *)
  200.     BEGIN
  201.       IF NoTrace THEN RETURN END;
  202.       WriteNl (dFile);
  203.       MakeSet (s,MAXTerm);
  204.  
  205.       (* finde alle Reduktionen die an einem Konflikt beteiligt sind *)
  206.  
  207.       WITH StateArrayPtr^[State] DO
  208.     MakeSet (EI,Size-1);
  209.     FOR Item := Items TO Items+Size-1 DO
  210.     WITH ItemArrayPtr^[Item] DO
  211.       IF Rep = RedRep THEN
  212.         Assign (s,CS);
  213.         Intersection (s,Set);
  214.         IF NOT IsEmpty (s) THEN
  215.  
  216.           (* Bearbeite konfliktbeladene Reduktion *)
  217.  
  218.           DebugRedItem (State, CS, Item, EI);
  219.         END;
  220.       END;
  221.     END;
  222.     END;
  223.     ReleaseSet (EI);
  224.       END;
  225.       ReleaseSet (s);
  226.     END DebugState;
  227.  
  228.   PROCEDURE DebugRedItem 
  229.     (      State : tStateIndex;       (* Zustand in dem der Konflikt auftritt *)
  230.       VAR CS    : tSet;           (* Conflict Set *)
  231.       Item    : tItemIndex;       (* am Konflikt beteiligte Reduktion *)
  232.       VAR EI    : tSet);       (* Explained Items *)
  233.   
  234.     VAR
  235.       T : tSet;
  236.       cs : tSet;
  237.       i : tItemIndex;
  238.       I : tItemIndex;
  239.       d : CARDINAL;
  240.       t : Terminal;
  241.       prod : tProduction;
  242.     BEGIN
  243.       MakeSet (cs,MAXTerm);
  244.       Assign (cs,CS);
  245.       FindPathC (cs,Item);    (* fuer Part C *)
  246.       UnRepPathC;
  247.       MakeSet (T,MAXTerm);
  248.  
  249.       i := PathC.path^[PathC.count];
  250.       WHILE NOT IsEmpty (cs) DO
  251.     t := Extract(cs);
  252.     WITH ItemArrayPtr^[i] DO
  253.       WITH StateArrayPtr^[Next] DO
  254.         I := Items;
  255.         LOOP
  256.           IF I >= Items+Size THEN EXIT END;
  257.  
  258.           (* Pruefe ob Terminal t moeglich *)
  259.  
  260.           IF Possible (I,t) THEN
  261.         
  262.         d := InitTab;  (* akt. Randabstand *)
  263.  
  264.         (* wie kommt man von Startsymbol zum Problem *)
  265.         prod := ADR (ProdArrayPtr^[ItemArrayPtr^[I].Prod]);
  266.         WritePartA (d,prod^.Left);
  267.  
  268.         (* wie kommt man zu Vorschauzeichen *)
  269.         WritePartB (d,I);
  270.  
  271.         (* wie kommt man zur linken Seite der Red *)
  272.         WritePartC (d,Item,t);
  273.  
  274.         (* womit kollidiert die Reduktion *)
  275.         WritePartD (d,State,t,Item,EI);
  276.  
  277.         WriteNl (dFile);
  278.         WriteNl (dFile);
  279.  
  280.         ReleaseArray (PathB.path,PathB.max,TSIZE(tItemIndex));
  281.         EXIT;
  282.  
  283.           END;
  284.           INC (I);
  285.         END;
  286.       END;
  287.     END;
  288.       END;
  289.       ReleaseSet (T);
  290.       ReleaseSet (cs);
  291.       ReleaseArray (PathC.path,PathC.max,TSIZE(tItemIndex));
  292.     END DebugRedItem;
  293.  
  294. PROCEDURE Possible (Item: tItemIndex; t: Terminal) : BOOLEAN;
  295.     TYPE triaer = (yes,no,maybe);
  296.     VAR 
  297.       state : tStateIndex;
  298.       prod  : tProdIndex;
  299.       pos   : tIndex;
  300.       reached : tSet;
  301.     
  302.     PROCEDURE Poss (state: tStateIndex; prod: tProdIndex; pos: tIndex; depth: CARDINAL) : triaer;
  303.       VAR
  304.     res : triaer;
  305.     nt  : NonTerminal;
  306.     item : tItemIndex;
  307.     Item : tItemIndex;
  308.     production : tProduction;
  309.       BEGIN
  310.  
  311.     (* finde zugh. item *)
  312.  
  313.     WITH StateArrayPtr^[state] DO
  314.       Item := Items;
  315.       LOOP
  316.         WITH ItemArrayPtr^[Item] DO
  317.           IF (Prod = prod) AND (Pos = pos) THEN
  318.         EXIT;
  319.           END;
  320.           INC (Item);
  321.         END;
  322.       END;
  323.     END;
  324.  
  325.     IF IsElement (Item,reached) THEN RETURN no; END;
  326.  
  327.     Include (reached, Item);
  328.  
  329.     WITH ItemArrayPtr^[Item] DO
  330.       CASE GetRep(Item) OF
  331.       | TermRep:
  332.           IF t = Read THEN
  333.           PathB.count := depth;
  334.           PathB.max := depth;
  335.           MakeArray (PathB.path,PathB.max,TSIZE(tItemIndex));
  336.           PathB.path^[depth] := Item;
  337.         Exclude (reached,Item);
  338.         RETURN yes;
  339.           ELSE
  340.         Exclude (reached,Item);
  341.         RETURN no;
  342.           END;
  343.       | RedRep:
  344.           Exclude (reached,Item);
  345.           RETURN maybe;
  346.       | NonTermRep:
  347.           res := no;
  348.           nt := Read;
  349.           WITH StateArrayPtr^[state] DO
  350.         FOR item := Items TO Items+Size-1 DO
  351.           WITH ItemArrayPtr^[item] DO
  352.             production := ADR (ProdArrayPtr^[Prod]);
  353.             IF production^.Left = nt THEN
  354.               CASE Poss (state,Prod,Pos,depth+1) OF
  355.               | yes:  
  356.              PathB.path^[depth] := Item;
  357.              Exclude (reached,Item);
  358.              RETURN yes;
  359.               | no:
  360.              ;
  361.               | maybe:
  362.              CASE Poss (ItemArrayPtr^[Item].Next,
  363.                     prod,pos+1,depth) OF
  364.              | yes:
  365.                Exclude (reached,Item);
  366.                RETURN yes;
  367.              | no:
  368.                 ;
  369.              | maybe:
  370.                  res := maybe;
  371.              END;
  372.               END;
  373.             END;
  374.           END;
  375.         END;
  376.           END;
  377.           Exclude (reached,Item);
  378.           RETURN res;
  379.       END;
  380.     END;
  381.       END Poss;
  382.     
  383. PROCEDURE GetRep (Item: tItemIndex) : tRep;
  384.     
  385.     (* Bestimme die zu Item gehoerige Repraesentantenart unabhaenig
  386.        vom Eintrag, es muss TermRep, NonTermRep oder RedRep
  387.        zurueckgeliefert werden, NoRep ist nicht zulaessig *)
  388.        
  389.       VAR prod : tProduction;
  390.       BEGIN
  391.     WITH ItemArrayPtr^[Item] DO
  392.       prod := ADR (ProdArrayPtr^[Prod]);
  393.       WITH prod^ DO
  394.         IF Pos = Len THEN
  395.           RETURN RedRep;
  396.         ELSIF (Right [Pos+1] >= MINTerm) AND (Right[Pos+1] <= MAXTerm) THEN
  397.           RETURN TermRep;
  398.         ELSE
  399.           RETURN NonTermRep;
  400.         END;
  401.       END;
  402.     END;
  403.       END GetRep;
  404.  
  405.     BEGIN
  406.       WITH ItemArrayPtr^[Item] DO
  407.     state := Number;
  408.     prod := Prod;
  409.     pos := Pos;
  410.       END;
  411.       MakeSet (reached,ItemIndex);
  412.       IF (Poss (state,prod,pos,1) = yes) THEN
  413.     ReleaseSet (reached);
  414.     RETURN TRUE;
  415.       ELSE
  416.     ReleaseSet (reached);
  417.     RETURN FALSE;
  418.       END;
  419.     END Possible;
  420.  
  421.   PROCEDURE FindPathC (VAR cs: tSet; Item: tItemIndex);
  422.     VAR
  423.       maxdepth : CARDINAL;
  424.       found : BOOLEAN;
  425.       i,u : tIndex;
  426.     BEGIN
  427.       maxdepth := 0;
  428.       found := FALSE;
  429.       REPEAT
  430.     INC (maxdepth);
  431.     WITH ItemArrayPtr^[Item].Relation DO
  432.       i := 1;
  433.       u := Used;
  434.       WHILE (i <= u) AND NOT found DO
  435.         SearchPathC (cs,maxdepth,0,Array^[i],found);
  436.         INC (i);
  437.       END;
  438.     END;
  439.       UNTIL found;
  440.     END FindPathC;
  441.  
  442. PROCEDURE SearchPathC (VAR cs       : tSet; maxdepth : CARDINAL; depth       : CARDINAL;
  443.       Item: tItemIndex; VAR found: BOOLEAN);
  444.     VAR
  445.       s : tSet;
  446.       i,u : tIndex;
  447.     BEGIN
  448.       WITH ItemArrayPtr^[Item] DO
  449.     INC (depth);
  450.     MakeSet (s,MAXTerm);
  451.     IF NOT EmptyReadSet THEN
  452.       Assign (s,ReadSet);
  453.     END;
  454.     Intersection (s,cs);
  455.     found := NOT IsEmpty (s);
  456.     IF found THEN
  457.       Assign (cs,s);
  458.     END;
  459.     ReleaseSet (s);
  460.     IF found THEN
  461.       PathC.count := depth;
  462.       PathC.max := depth;
  463.       MakeArray (PathC.path,PathC.max,TSIZE(tItemIndex));
  464.       PathC.path^[depth] := Item;
  465.     ELSIF depth < maxdepth THEN
  466.       WITH ItemArrayPtr^[Item].Relation DO
  467.         i := 1;
  468.         u := Used;
  469.         WHILE (i <= u) AND NOT found DO
  470.           SearchPathC (cs,maxdepth,depth,Array^[i],found);
  471.           INC (i);
  472.         END;
  473.         IF found THEN
  474.           PathC.path^[depth] := Item;
  475.         END;
  476.       END;
  477.     END;
  478.       END;
  479.     END SearchPathC;
  480.  
  481. PROCEDURE UnRepPathC;
  482.     VAR
  483.       State : tStateIndex;
  484.       PathItem, Item : tItemIndex;
  485.       i,j : CARDINAL;
  486.       prod : tProduction;
  487.       PathVal,val : tIndex;
  488.  
  489.     (* Waehle moeglichst kurz zu beendende Items aus *)
  490.  
  491.     BEGIN
  492.       WITH PathC DO
  493.     FOR i:=1 TO count-1 DO
  494.       PathItem := path^[i];
  495.       prod := ADR (ProdArrayPtr^[ItemArrayPtr^[PathItem].Prod]);
  496.       PathVal := 0;
  497.       FOR j := ItemArrayPtr^[PathItem].Pos+1 TO prod^.Len DO
  498.         INC (PathVal,Value[prod^.Right[j]]);
  499.       END;
  500.       State := ItemArrayPtr^[PathItem].Number;
  501.       WITH StateArrayPtr^[State] DO
  502.         FOR Item := Items TO Items+Size-1 DO
  503.           IF ItemArrayPtr^[Item].RepNo = ItemArrayPtr^[PathItem].RepNo THEN
  504.         prod := ADR (ProdArrayPtr^[ItemArrayPtr^[Item].Prod]);
  505.         val := 0;
  506.         FOR j := ItemArrayPtr^[Item].Pos+1 TO prod^.Len DO
  507.           INC (val,Value[prod^.Right[j]]);
  508.         END;
  509.         IF val < PathVal THEN
  510.           PathItem := Item;
  511.           PathVal := val;
  512.         END;
  513.           END;
  514.         END;
  515.       END;
  516.       path^[i] := PathItem;
  517.     END;
  518.       END;
  519.     END UnRepPathC;
  520.  
  521. PROCEDURE WritePartA (VAR d: CARDINAL; N: NonTerminal);
  522.   
  523.   (* Drucke den Trace vom Startsymbol zum Nichtterminal N *)
  524.  
  525.     VAR i,j : CARDINAL;
  526.     BEGIN
  527.       FindPathA (N);
  528.       WITH PathA DO
  529.     FOR i:=1 TO count DO
  530.       WriteTab (d);
  531.       WriteProd (path^[i].Prod,path^[i].Pos,d);
  532.       WriteNl (dFile);
  533.       IF (d > MaxTabA) OR ((i = count) AND (d > InitTab)) THEN 
  534.         WriteTab(InitTab);
  535.         FOR j:=InitTab+1 TO d DO
  536.           WriteC (dFile,'.');
  537.         END;
  538.         WriteC  (dFile,':');
  539.         WriteNl (dFile);
  540.         d := InitTab;
  541.         WriteTab (d);
  542.         WriteC (dFile,':');
  543.         WriteNl (dFile);
  544.       END;
  545.     END;
  546.       END;
  547.       ReleaseArray (PathA.path,PathA.max,TSIZE(tProdPathElmt));
  548.     END WritePartA;
  549.  
  550. PROCEDURE FindPathA (N: NonTerminal);
  551.     VAR
  552.       maxdepth : CARDINAL;
  553.       found    : BOOLEAN;
  554.       rNTs : tSet;  (* reached Nonterminals *)
  555.     BEGIN
  556.       maxdepth := 0;
  557.       found := FALSE;
  558.       MakeSet (rNTs,MAXNonTerm);
  559.  
  560.       REPEAT
  561.     INC (maxdepth);
  562.     SearchPathA (StartSymbol,N,maxdepth,0,found,rNTs);
  563.       UNTIL found;
  564.       ReleaseSet (rNTs);
  565.     END FindPathA;
  566.   
  567.   PROCEDURE SearchPathA (From: NonTerminal; To: NonTerminal;
  568.      maxdepth: CARDINAL; depth: CARDINAL; VAR found: BOOLEAN; VAR rNTs: tSet);
  569.     VAR
  570.       prod : tProduction;
  571.       prodindex : tProdIndex;
  572.       pos : tIndex;
  573.       i,u : tIndex;
  574.     BEGIN
  575.       IF From = To THEN
  576.     WITH PathA DO
  577.       count := depth;
  578.       max    := depth;
  579.       MakeArray (path,max,TSIZE(tProdPathElmt));
  580.       found := TRUE;
  581.     END;
  582.       ELSIF depth < maxdepth THEN
  583.  
  584.     (* Betrachte alle zu From gehoerige Produktionen *)
  585.  
  586.     WITH ProdList[From] DO
  587.       u := Used;
  588.       FOR i := 1 TO u DO
  589.         
  590.         (* Betrachte eine einzelne Produktion *)
  591.  
  592.         prodindex := Array^[i].Index;
  593.         prod := ADR (ProdArrayPtr^[prodindex]);
  594.         WITH prod^ DO
  595.           FOR pos := 1 TO Len DO
  596.         IF (Right[pos] >= MINNonTerm) 
  597.            AND (Right[pos] <= MAXNonTerm) THEN
  598.  
  599.           (* Nichtterminale auf der rechten Seite weiterverfolgen *)
  600.  
  601.           IF NOT IsElement (Right[pos],rNTs) THEN
  602.  
  603.             Include (rNTs,Right[pos]);
  604.             SearchPathA (Right[pos],To,maxdepth,depth+1,found,rNTs);
  605.             Exclude (rNTs,Right[pos]);
  606.  
  607.           END;
  608.  
  609.           IF found THEN
  610.             
  611.             (* Pfad festhalten *)
  612.  
  613.             PathA.path^[depth+1].Prod := prodindex;
  614.  
  615.             (* Position vor dem Nichtterminal angeben *)
  616.  
  617.             PathA.path^[depth+1].Pos := pos-1;
  618.  
  619.             RETURN;
  620.           END;
  621.         END;
  622.           END;
  623.         END;
  624.       END;
  625.     END;
  626.       END;
  627.     END SearchPathA;
  628.  
  629. PROCEDURE WritePartB (VAR d: CARDINAL; I: tItemIndex);
  630.     VAR
  631.       p : tProdIndex;
  632.       l : tIndex;
  633.       l1 : tIndex;
  634.       length : CARDINAL;
  635.       i,j : CARDINAL;
  636.       d1 : CARDINAL;
  637.       prod : tProduction;
  638.     BEGIN
  639.       p := ItemArrayPtr^[I].Prod;
  640.       l := ItemArrayPtr^[I].Pos-1;
  641.       l1 := ItemArrayPtr^[PathB.path^[1]].Pos;
  642.       d1 := 0;
  643.       WriteTab (d);
  644.  
  645.       prod := ADR(ProdArrayPtr^[p]);
  646.       WITH prod^ DO
  647.     FOR i:=1 TO Len DO
  648.       WriteVoc (Right[i],length);
  649.       WriteS (dFile,' ');
  650.       IF i <= l THEN
  651.         INC (d,length+1);
  652.       ELSIF i <= l1 THEN
  653.         INC (d1,length+1);
  654.       END;
  655.     END;
  656.       END;
  657.  
  658.       DEC (d1);      (* Laenge von ':' *)
  659.       WriteNl (dFile);
  660.  
  661.       WITH PathB DO
  662.     FOR i:=2 TO count DO
  663.       IF (d+d1+1 > MaxTabB) AND (d1>1) THEN 
  664.         WriteTab(d);
  665.         WriteS (dFile,': ');
  666.         FOR j:=2 TO d1 DO
  667.           WriteC (dFile,'.');
  668.         END;
  669.         WriteC (dFile,':');
  670.         WriteNl (dFile);
  671.         WriteTab(d);
  672.         WriteS (dFile,': :');
  673.         WriteNl (dFile);
  674.         d1 := 1;
  675.       END;
  676.       p := ItemArrayPtr^[path^[i]].Prod;
  677.       l := ItemArrayPtr^[path^[i]].Pos;
  678.       WriteTab (d);
  679.       WriteC (dFile,':');
  680.       WriteTab (d1);
  681.       WriteProd (p,l,d1);
  682.       WriteNl (dFile);
  683.     END;
  684.       END;
  685.       WriteTab (d);
  686.       WriteC (dFile,':');
  687.       WriteNl (dFile);
  688.     END WritePartB;
  689.  
  690. PROCEDURE WritePartC (VAR d: CARDINAL; I: tItemIndex; t: Terminal);
  691.     VAR
  692.       i,j : CARDINAL;
  693.       p : tProdIndex;
  694.       l : CARDINAL;
  695.       prod : tProduction;
  696.       d1 : CARDINAL;
  697.     BEGIN
  698.       WITH PathC DO
  699.     FOR i:=count-1 TO 1 BY -1 DO
  700.       IF d > MaxTabC THEN 
  701.         WriteTab(InitTab);
  702.         FOR j:=InitTab+1 TO d DO
  703.           WriteC (dFile,'.');
  704.         END;
  705.         WriteC  (dFile,':');
  706.         WriteNl (dFile);
  707.         d := InitTab;
  708.         WriteTab (d);
  709.         WriteC (dFile,':');
  710.         WriteNl (dFile);
  711.       END;
  712.       p := ItemArrayPtr^[path^[i]].Prod;
  713.       l := ItemArrayPtr^[path^[i]].Pos;
  714.       WriteTab (d);
  715.       WriteProd (p,l,d);
  716.       WriteNl (dFile);
  717.     END;
  718.       END;
  719.  
  720.       (* Fortsetzung fuer Reduce *)
  721.  
  722.       prod := ADR (ProdArrayPtr^[ItemArrayPtr^[I].Prod]);
  723.       d1 := d;
  724.       p := ItemArrayPtr^[I].Prod;
  725.       l := ItemArrayPtr^[I].Pos;
  726.       WriteTab (d1);
  727.       WriteProd (p,l,d1);
  728.       WriteNl (dFile);
  729.  
  730.       (* erlaeutere Reduce *)
  731.  
  732.       l := VocLength (prod^.Left);
  733.       IF d >= 4+7+l THEN 
  734.     DEC (d,4+7+l);        (* Laenge Text 'reduce ' + Laenge linke Seite *)
  735.       ELSE            (* = Laenge ' -> ' *)
  736.     WriteTab (d);
  737.     WriteC (dFile,':');
  738.     FOR j:=d+1 TO 4+7+l DO
  739.       WriteC (dFile,'.');
  740.     END;
  741.     WriteNl (dFile);
  742.     WriteTab (4+7+l);
  743.     WriteC (dFile,':');
  744.     WriteNl (dFile);
  745.     d := 0;
  746.       END;
  747.  
  748.       WITH prod^ DO
  749.     WriteTab (d);
  750.     WriteS (dFile,'reduce ');
  751.     WriteVoc (Left,l);
  752.     WriteS (dFile,' -> ');
  753.     IF Len = 0 THEN
  754.       WriteS (dFile,'-Epsilon-');
  755.     ELSE
  756.       FOR i:=1 TO Len DO
  757.         WriteVoc (Right[i],l);
  758.         IF i < Len THEN
  759.           WriteC (dFile,' ');
  760.         END;
  761.       END;
  762.     END;
  763.     WriteS (dFile,'. {');
  764.     WriteVoc (t,l);
  765.     WriteS (dFile,'} ?');
  766.     WriteNl(dFile);
  767.       END;
  768.     END WritePartC;
  769.  
  770. PROCEDURE WritePartD (dist: CARDINAL; State: tStateIndex; t: Terminal; RedItem: tItemIndex; EI: tSet);
  771.   VAR
  772.       Item : tItemIndex;
  773.       prod : tProduction;
  774.       i,j,l   : CARDINAL;
  775.       d : CARDINAL;
  776.       RedProd : tProduction;
  777.   BEGIN
  778.     RedProd := ADR (ProdArrayPtr^ [ItemArrayPtr^ [RedItem].Prod]);
  779.     WITH StateArrayPtr^[State] DO
  780.       FOR Item := Items TO Items+Size-1 DO
  781.     WITH ItemArrayPtr^[Item] DO
  782.       IF (Read = t) AND NOT IsElement (Item-Items, EI) THEN
  783.         Include (EI, Item-Items);
  784.         d := InitTab;
  785.  
  786.         prod := ADR (ProdArrayPtr^[Prod]);
  787.         WITH prod^ DO
  788.           IF (Pos # ItemArrayPtr^[RedItem].Pos) OR
  789.          (Left # RedProd^.Left) THEN
  790.         (* Drucke Trace fuer Read - Ableitung von Startzustand *)
  791.  
  792.         WriteNl (dFile);
  793.         FindPathD (Left,State);
  794.  
  795.         WITH PathD DO
  796.           FOR i:=1 TO count - 1 DO
  797.             WriteTab (d);
  798.             WriteProd (path^[i].Prod,path^[i].Pos,d);
  799.             WriteNl (dFile);
  800.             IF d > MaxTabD THEN 
  801.               WriteTab(InitTab);
  802.               FOR j:=InitTab+1 TO d DO
  803.             WriteC (dFile,'.');
  804.               END;
  805.               WriteC  (dFile,':');
  806.               WriteNl (dFile);
  807.               d := InitTab;
  808.               WriteTab (d);
  809.               WriteC (dFile,':');
  810.               WriteNl (dFile);
  811.             END;
  812.           END;
  813.         END;
  814.         ReleaseArray (PathD.path,PathD.max,TSIZE(tProdPathElmt));
  815.  
  816.         WriteTab (d);
  817.         WriteProd (Prod,0,d);
  818.         WriteNl (dFile);
  819.  
  820.         l := VocLength (Left);
  821.         IF d >= 4+7+l THEN 
  822.           DEC (d,4+7+l);      (* Laenge Text 'read   ' *)
  823.                       (* + Laenge linke Seite *)
  824.         ELSE              (* + Laenge ' -> ' *)
  825.           WriteTab (d);
  826.           WriteC (dFile,':');
  827.           FOR j:=d+1 TO 4+7+l DO
  828.             WriteC (dFile,'.');
  829.           END;
  830.           WriteNl (dFile);
  831.           WriteTab (4+7+l);
  832.           WriteC (dFile,':');
  833.           WriteNl (dFile);
  834.           d := 0;
  835.         END;
  836.           ELSE
  837.         (* Trace der Reduktion passt zum Read *)
  838.         (* selbe Distanz wie bei Reduktion verwenden *)
  839.  
  840.         d := dist;
  841.           END;
  842.  
  843.           (* erlaeutere Read *)
  844.  
  845.           WriteTab (d);
  846.           WriteS (dFile,'read   ');
  847.           WriteVoc (Left,l);
  848.           WriteS (dFile,' -> ');
  849.           IF Pos = 0 THEN
  850.         WriteC (dFile,'.');
  851.           END;
  852.           FOR i:=1 TO Len DO
  853.         WriteVoc (Right[i],l);
  854.         IF i = Pos THEN
  855.           WriteC (dFile,'.');
  856.         ELSIF i < Len THEN
  857.           WriteC (dFile,' ');
  858.         END;
  859.           END;
  860.           WriteS (dFile,' ?');
  861.         END;
  862.         WriteNl (dFile);
  863.       END;
  864.     END;
  865.       END;
  866.     END;
  867.     END WritePartD;
  868.  
  869. PROCEDURE MakeChainD;
  870.   VAR
  871.     LastCount : LONGINT;
  872.     Item, I : tItemIndex;
  873.     State : tStateIndex;
  874.     read  : Vocabulary;
  875.     prod  : tProduction;
  876.  
  877.     PROCEDURE PutInChain (Item: tItemIndex; Last: tIndex);
  878.     VAR
  879.       prod  : tProduction;
  880.       State : tStateIndex;
  881.       I        : tItemIndex;
  882.     BEGIN
  883.  
  884.       (* Zum Item gehoerige Produktion *)
  885.  
  886.       prod := ADR (ProdArrayPtr^[ItemArrayPtr^[Item].Prod]);
  887.  
  888.       (* Betrachte alle zur Produktion gehoerigen Items *)
  889.  
  890.       WHILE (ItemArrayPtr^[Item].Pos < prod^.Len) AND
  891.         NOT IsElement (Item, ChainD.reached) DO
  892.  
  893.     (* Item in Kette eintragen *)
  894.  
  895.     WITH ChainD DO
  896.       INC (count);
  897.       IF count > max THEN
  898.         ExtendArray (chain, max, TSIZE (tItemChainElmt));
  899.       END;
  900.       chain^ [count].Last := Last;
  901.       chain^ [count].Item := Item;
  902.       Include (reached, Item);
  903.     END;
  904.  
  905.     (* Punkt nach rechts schieben *)
  906.  
  907.     State := ItemArrayPtr^[Item].Next;    (* Folgezustand *)
  908.     I := StateArrayPtr^[State].Items;     (* erstes Item *)
  909.  
  910.     (* suche Item mit selber Produktion und um 1 groesserer Position *)
  911.     WHILE (ItemArrayPtr^[I].Prod # ItemArrayPtr^[Item].Prod) OR
  912.           (ItemArrayPtr^[I].Pos # ItemArrayPtr^[Item].Pos+1) DO
  913.       INC (I);
  914.     END;
  915.     Item := I;
  916.       END;
  917.     END PutInChain;
  918.  
  919.   BEGIN
  920.  
  921.     (* Chain initialisieren *)
  922.  
  923.     WITH ChainD DO
  924.       max := InitChainLength;
  925.       count := 0;
  926.       level := 0;
  927.       MakeArray (chain, max, TSIZE (tItemChainElmt));
  928.       MakeSet (reached, ItemIndex);
  929.       PutInChain (1, 0);
  930.  
  931.       LOOP 
  932.     WITH ChainD DO
  933.       LastCount := count;
  934.  
  935.       IF level = LastCount THEN EXIT END;
  936.  
  937.       WHILE level < LastCount DO
  938.         INC (level);
  939.         Item := chain^ [level].Item;
  940.  
  941.         (* Falls Nichtterminal nach dem Punkt steht, wird
  942.            weiterverfolgt *)
  943.  
  944.         read := ItemArrayPtr^[Item].Read;
  945.         IF (read >= MINNonTerm) AND (read <= MAXNonTerm) THEN
  946.  
  947.           (* moegliche Fortsetzungen betrachten *)
  948.  
  949.           State := ItemArrayPtr^[Item].Number;
  950.           FOR I := StateArrayPtr^[State].Items TO
  951.                StateArrayPtr^[State].Items + StateArrayPtr^[State].Size - 1 DO
  952.         WITH ItemArrayPtr^ [I] DO
  953.           prod := ADR (ProdArrayPtr^[Prod]);
  954.           IF (prod^.Left = read) AND 
  955.              (ItemArrayPtr^[I].Pos = 0) THEN
  956.  
  957.             PutInChain (I, level);
  958.            
  959.           END;
  960.         END;
  961.           END;
  962.         END;
  963.       END;
  964.     END;
  965.       END;
  966.     END;
  967.   END MakeChainD;
  968.  
  969. PROCEDURE FindPathD (NT: NonTerminal; EndState: tStateIndex);
  970.     VAR 
  971.       last, level : LONGINT;
  972.       prod : tProduction;
  973.       I : tItemIndex;
  974.       Depth : tIndex;
  975.   BEGIN
  976.  
  977.     (* evtl. (d.h. beim ersten mal) Kette aufbauen *)
  978.  
  979.     IF ChainD.max = 0 THEN
  980.       MakeChainD;
  981.     END;
  982.  
  983.     WITH ChainD DO;
  984.  
  985.       (* Item suchen *)
  986.  
  987.       last := 0;
  988.       LOOP
  989.     INC (last);
  990.     I := chain^ [last].Item;
  991.     IF (ItemArrayPtr^[I].Number = EndState) THEN
  992.       prod := ADR (ProdArrayPtr^[ItemArrayPtr^[I].Prod]);
  993.       IF NT = prod^.Left THEN
  994.         EXIT;
  995.       END;
  996.     END;
  997.       END;
  998.  
  999.       (* Tiefe bestimmen *)
  1000.  
  1001.       Depth := 0;
  1002.       level := last;
  1003.  
  1004.       WHILE level # 0 DO
  1005.     INC (Depth);
  1006.     level := chain^ [level].Last;
  1007.       END;
  1008.  
  1009.       (* Chain in Path uebertragen *)
  1010.    
  1011.       WITH PathD DO
  1012.     count := Depth;
  1013.     max   := Depth;
  1014.     MakeArray (path, max, TSIZE (tProdPathElmt));
  1015.       END;
  1016.  
  1017.       level := last;
  1018.       WHILE Depth > 0 DO
  1019.     I := chain^ [level].Item;
  1020.     PathD.path^ [Depth].Prod := ItemArrayPtr^[I].Prod;
  1021.     PathD.path^ [Depth].Pos     := ItemArrayPtr^[I].Pos;
  1022.     DEC (Depth);
  1023.     level := chain^[level].Last;
  1024.       END;
  1025.     END;
  1026.   END FindPathD;
  1027.  
  1028. PROCEDURE WriteProd (p: tProdIndex; l: tIndex; VAR d: CARDINAL);
  1029.     VAR
  1030.       prod : tProduction;
  1031.       i : tIndex;
  1032.       length  : CARDINAL;
  1033.     BEGIN
  1034.       prod := ADR(ProdArrayPtr^[p]);
  1035.       WITH prod^ DO
  1036.     IF Len = 0 THEN
  1037.       WriteS (dFile,'-Epsilon-');
  1038.     ELSE
  1039.       FOR i:=1 TO Len DO
  1040.         WriteVoc (Right[i],length);
  1041.         WriteS (dFile,' ');
  1042.         IF i <= l THEN
  1043.           INC (d,length+1);
  1044.         END;
  1045.       END;
  1046.     END;
  1047.       END;
  1048.     END WriteProd;
  1049.  
  1050. PROCEDURE WriteVoc (voc: Vocabulary; VAR length: CARDINAL);
  1051.     VAR
  1052.       sym : tIdent;
  1053.       str : tString;
  1054.       err : TokenError;
  1055.       i : CARDINAL;
  1056.     BEGIN
  1057.       sym := TokenToSymbol (voc,err);
  1058.       GetString (sym,str);
  1059.       length := Length (str);
  1060.       FOR i := 1 TO length DO
  1061.     WriteC (dFile,Char (str, i));
  1062.       END;
  1063.     END WriteVoc;
  1064.  
  1065. PROCEDURE VocLength (voc: Vocabulary): CARDINAL;
  1066.     VAR
  1067.       sym : tIdent;
  1068.       str : tString;
  1069.       err : TokenError;
  1070.     BEGIN
  1071.       sym := TokenToSymbol (voc,err);
  1072.       GetString (sym,str);
  1073.       RETURN Length (str);
  1074.     END VocLength;
  1075.     
  1076. PROCEDURE WriteTab (d: CARDINAL);
  1077.     VAR i : CARDINAL;
  1078.     BEGIN
  1079.       FOR i := 1 TO d DO
  1080.     WriteC (dFile,' ');
  1081.       END;
  1082.     END WriteTab;
  1083.  
  1084. BEGIN
  1085.   NoTrace := FALSE;
  1086.   ChainD.max := 0;
  1087. END Debug.
  1088.